import { Player, PlayerType } from "./Player.js";
import { PokerType, PokerCard, PokerCardOpt } from "./PokerCard.js";
import { MsgData } from "./Rule.js";

/** 创建一副牌 */
export const createPoker = () => {
  /** 扑克的集合 */
  const list: PokerCard[] = [];
  let n: PokerCardOpt["val"] = 1;
  // 各花色的13张牌
  while (n < 14) {
    [PokerType.spade, PokerType.heart, PokerType.club, PokerType.diamond].forEach((type) => {
      list.push(new PokerCard({ val: n, type: type }));
    });
    n += 1;
  }
  // 小王
  list.push(new PokerCard({ val: 14, type: PokerType.joker }));
  // 大王
  list.push(new PokerCard({ val: 15, type: PokerType.joker }));
  return list;
};

/**
 * 洗牌
 * @param cards 需要洗的牌的集合
 */
export const shuffle = (cards: PokerCard[]) => {
  const list: PokerCard[] = [...cards];
  const newList: PokerCard[] = [];

  while (list.length) {
    const index = Math.random() * list.length;
    newList.push(...list.splice(index, 1));
  }

  return newList;
};

/** 扑克服务 */
export class PokerServer {
  /** 还在客户端的牌 */
  private poker: PokerCard[] = [];
  /** 玩家 */
  private player: Player;
  /** 电脑控制的玩家A */
  private playerA: Player;
  /** 电脑控制的玩家B */
  private playerB: Player;
  /** 消息的监听回调函数列表 */
  private msgCallBackList: ((msg: string) => void)[] = [];
  constructor() {
    this.player = new Player();
    this.playerA = new Player();
    this.playerB = new Player();
    this.init();
  }

  /** 初始化(洗牌并发牌) */
  private init() {
    this.poker = shuffle(createPoker());
    this.player.receive(this.poker.splice(3, 17));
    this.playerA.receive(this.poker.splice(3, 17));
    this.playerB.receive(this.poker.splice(3, 17));

    // TODO 抢地主，现在默认玩家为地主
    this.player.type = PlayerType.landlord;
    this.player.receive(this.poker);
  }
  /** 重置 */
  public reset() {
    this.player.reset();
    this.playerA.reset();
    this.playerB.reset();
    this.init();
  }
  /** 提供给客户端用的监听信息 */
  public onMsg(fn: (msg: string) => void) {
    if (typeof fn === "function") {
      this.msgCallBackList.push(fn);
    }
  }

  /** 发送信息 */
  private sendMsg(msg: string) {
    this.msgCallBackList.forEach((fn) => {
      fn(msg);
    });
  }

  /** 接收客户端给服务器的信息 */
  public receive(msg: string) {
    let data: MsgData = {} as MsgData;
    try {
      data = JSON.parse(msg) || {};
    } catch (err) {
      console.warn(err);
    }

    if (data.type === "start") {
      this.sendMsg(
        JSON.stringify({
          type: "deal",
          data: this.player.cardList.map((v) => ({ val: v.value, type: v.type })),
        } as MsgData)
      );
    }

    // 用户出牌
    if (data.type === "player") {
      // TODO 验证是否玩家有这些牌
      // TODO 验证是否比当前出牌大
      // TODO 扣除本地的相应人的扑克，判断是否获得胜利,并且发消息给各个用户
      this.sendMsg(
        JSON.stringify({
          type: "player",
          data: data.data,
        })
      );
    }
  }
  // /** 发送给单机用户的牌 */
  // public sendPlayerCard() {
  //   return this.player.cardList.map((v) => new PokerCard({ val: v.value, type: v.type }));
  // }

  // TODO 接收消息
  // TODO 发送消息
  // TODO 接收消息-接收玩家的出牌（检验），并转发给其它玩家，以及判断输赢
  // TODO 接收消息-接收抢地主的申请
  // TODO 接收消息-接收加倍的申请
}
